package com.pethospital.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pethospital.dto.AppointmentDTO;
import com.pethospital.entity.Appointment;
import com.pethospital.entity.Department;
import com.pethospital.entity.Pet;
import com.pethospital.entity.Staff;
import com.pethospital.entity.Review;
import com.pethospital.entity.User;
import com.pethospital.exception.BusinessException;
import com.pethospital.mapper.AppointmentMapper;
import com.pethospital.mapper.PetMapper;
import com.pethospital.mapper.StaffMapper;
import com.pethospital.mapper.UserMapper;
import com.pethospital.service.AppointmentService;
import com.pethospital.service.PetService;
import com.pethospital.service.StaffService;
import com.pethospital.service.ReviewService;
import com.pethospital.service.DepartmentService;
import com.pethospital.service.UserService;
import com.pethospital.util.SpringContextUtil;
import com.pethospital.vo.AppointmentVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 预约服务实现类
 */
@Slf4j
@Service
public class AppointmentServiceImpl extends ServiceImpl<AppointmentMapper, Appointment> implements AppointmentService {

    @Resource
    private PetMapper petMapper;

    @Resource
    private StaffMapper staffMapper;

    @Resource
    private PetService petService;

    @Resource
    private StaffService staffService;

    @Resource
    private ReviewService reviewService;

    @Resource
    private DepartmentService departmentService;

    @Resource
    private UserService userService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createAppointment(AppointmentDTO appointmentDTO, Long userId) {
        // 验证宠物是否存在且属于当前用户
        Pet pet = petMapper.selectById(appointmentDTO.getPetId());
        if (pet == null) {
            throw new BusinessException("宠物不存在");
        }
        if (!pet.getUserId().equals(userId)) {
            throw new BusinessException("无权操作此宠物");
        }

        // 验证医护人员是否存在
        Staff staff = staffMapper.selectById(appointmentDTO.getStaffId());
        if (staff == null) {
            throw new BusinessException("医护人员不存在");
        }

        // 创建预约
        Appointment appointment = new Appointment();
        appointment.setUserId(userId);
        appointment.setPetId(appointmentDTO.getPetId());
        appointment.setStaffId(appointmentDTO.getStaffId());
        appointment.setDepartmentId(staff.getDepartmentId());
        appointment.setAppointmentTime(appointmentDTO.getAppointmentTime());
        appointment.setType(appointmentDTO.getType());
        appointment.setDescription(appointmentDTO.getDescription());
        appointment.setRemark(appointmentDTO.getRemark());
        appointment.setStatus(0); // 0-待确认
        appointment.setCreateTime(LocalDateTime.now());
        appointment.setUpdateTime(LocalDateTime.now());
        save(appointment);
        return appointment.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelAppointment(Long id, Long userId) {
        // 查询预约
        Appointment appointment = getOne(new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getId, id)
                .eq(Appointment::getUserId, userId));
        
        if (appointment == null) {
            throw new BusinessException("预约不存在或不属于当前用户");
        }
        
        // 验证状态
        if (appointment.getStatus() != 0 && appointment.getStatus() != 1) {
            throw new BusinessException("当前状态不可取消");
        }
        
        // 更新状态
        appointment.setStatus(3); // 3-已取消
        appointment.setUpdateTime(LocalDateTime.now());
        
        updateById(appointment);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeAppointment(Long id, Long staffId) {
        // 检查预约是否存在且属于当前医护人员
        Appointment appointment = getOne(new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getId, id)
                .eq(Appointment::getStaffId, staffId));
        
        if (appointment == null) {
            throw new BusinessException("预约不存在或不属于当前医护人员");
        }
        
        // 验证状态
        if (appointment.getStatus() != 1) {
            throw new BusinessException("当前状态不可完成");
        }
        
        // 更新状态
        appointment.setStatus(2); // 2-已完成
        appointment.setUpdateTime(LocalDateTime.now());
        
        updateById(appointment);
    }

    @Override
    public Appointment getAppointment(Long id, Long userId) {
        log.info("获取预约详情, id: {}, userId: {}", id, userId);
        
        // 查询预约
        Appointment appointment = getOne(new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getId, id)
                .eq(Appointment::getUserId, userId)
                .or()
                .eq(Appointment::getStaffId, userId));
        
        if (appointment == null) {
            throw new BusinessException("预约不存在或无权查看此预约");
        }
        
        log.info("预约基本信息: {}", appointment);
        
        // 将预约ID设置为预约号(appointmentNo)
        appointment.setExtra("appointmentNo", appointment.getId().toString());
        
        // 查询并填充用户信息
        if (appointment.getUserId() != null) {
            User user = userService.getById(appointment.getUserId());
            if (user != null) {
                log.info("用户信息: id={}, nickname={}", user.getId(), user.getNickname());
                // 设置用户名到extraData中
                appointment.setExtra("username", user.getNickname() != null ? user.getNickname() : "未知用户");
            } else {
                log.warn("用户信息未找到: userId={}", appointment.getUserId());
                appointment.setExtra("username", "未知用户");
            }
        } else {
            appointment.setExtra("username", "未知用户");
        }
        
        // 查询并填充宠物信息
        if (appointment.getPetId() != null) {
            Pet pet = petService.getById(appointment.getPetId());
            if (pet != null) {
                log.info("宠物信息: id={}, name={}", pet.getId(), pet.getName());
                // 直接设置辅助字段
                appointment.setPetName(pet.getName());
                // 同时设置到extraData中保持兼容
                appointment.setExtra("petName", pet.getName());
            } else {
                log.warn("宠物信息未找到: petId={}", appointment.getPetId());
            }
        }
        
        // 查询并填充医生信息
        if (appointment.getStaffId() != null) {
            Staff staff = staffService.getById(appointment.getStaffId());
            if (staff != null) {
                log.info("医生信息: id={}, name={}", staff.getId(), staff.getName());
                appointment.setStaffName(staff.getName());
                appointment.setExtra("staffName", staff.getName());
            } else {
                log.warn("医生信息未找到: staffId={}", appointment.getStaffId());
            }
        }
        
        // 查询并填充科室信息
        if (appointment.getDepartmentId() != null) {
            Department department = departmentService.getById(appointment.getDepartmentId());
            if (department != null) {
                log.info("科室信息: id={}, name={}", department.getId(), department.getName());
                appointment.setDepartmentName(department.getName());
                appointment.setExtra("departmentName", department.getName());
            } else {
                log.warn("科室信息未找到: departmentId={}", appointment.getDepartmentId());
            }
        }
        
        // 查询关联的评价信息
        Review review = reviewService.getReviewByAppointmentId(appointment.getId());
        if (review != null) {
            log.info("评价信息: id={}, score={}", review.getId(), review.getScore());
            appointment.setReview(review);
            appointment.setExtra("review", review);
        }
        
        log.info("填充关联信息后的预约数据: {}", appointment);
        
        return appointment;
    }

    @Override
    public Page<Appointment> getUserAppointments(Long userId, Integer status, int page, int size) {
        LambdaQueryWrapper<Appointment> wrapper = new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getUserId, userId)
                .orderByDesc(Appointment::getCreateTime);
        
        if (status != null) {
            wrapper.eq(Appointment::getStatus, status);
        }
        
        Page<Appointment> appointmentPage = page(new Page<>(page, size), wrapper);
        
        // 填充关联数据
        fillAssociatedData(appointmentPage.getRecords());
        
        return appointmentPage;
    }

    @Override
    public Page<Appointment> getStaffAppointments(Long staffId, Integer status, int page, int size) {
        LambdaQueryWrapper<Appointment> wrapper = new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getStaffId, staffId)
                .orderByAsc(Appointment::getAppointmentTime);
        
        if (status != null) {
            wrapper.eq(Appointment::getStatus, status);
        }
        
        Page<Appointment> appointmentPage = page(new Page<>(page, size), wrapper);
        
        // 填充关联数据
        fillAssociatedData(appointmentPage.getRecords());
        
        return appointmentPage;
    }

    /**
     * 填充预约列表的关联数据
     * @param appointments 预约列表
     */
    private void fillAssociatedData(Iterable<Appointment> appointments) {
        for (Appointment appointment : appointments) {
            // 添加预约号(appointmentNo)
            appointment.setExtra("appointmentNo", appointment.getId().toString());
            
            // 查询并填充用户信息
            if (appointment.getUserId() != null) {
                User user = userService.getById(appointment.getUserId());
                if (user != null) {
                    log.info("用户信息: id={}, nickname={}", user.getId(), user.getNickname());
                    // 设置用户名到extraData中
                    appointment.setExtra("username", user.getNickname() != null ? user.getNickname() : "未知用户");
                } else {
                    log.warn("用户信息未找到: userId={}", appointment.getUserId());
                    appointment.setExtra("username", "未知用户");
                }
            } else {
                appointment.setExtra("username", "未知用户");
            }
            
            // 查询并填充宠物信息
            if (appointment.getPetId() != null) {
                Pet pet = petService.getById(appointment.getPetId());
                if (pet != null) {
                    log.info("宠物信息: id={}, name={}", pet.getId(), pet.getName());
                    // 直接设置辅助字段
                    appointment.setPetName(pet.getName());
                    // 同时设置到extraData中保持兼容
                    appointment.setExtra("petName", pet.getName());
                }
            }
            
            // 查询并填充医生信息
            if (appointment.getStaffId() != null) {
                Staff staff = staffService.getById(appointment.getStaffId());
                if (staff != null) {
                    log.info("医生信息: id={}, name={}", staff.getId(), staff.getName());
                    appointment.setStaffName(staff.getName());
                    appointment.setExtra("staffName", staff.getName());
                }
            }
            
            // 查询并填充科室信息
            if (appointment.getDepartmentId() != null) {
                Department department = departmentService.getById(appointment.getDepartmentId());
                if (department != null) {
                    log.info("科室信息: id={}, name={}", department.getId(), department.getName());
                    appointment.setDepartmentName(department.getName());
                    appointment.setExtra("departmentName", department.getName());
                }
            }
            
            // 查询关联的评价信息
            Review review = reviewService.getReviewByAppointmentId(appointment.getId());
            if (review != null) {
                log.info("评价信息: id={}, score={}", review.getId(), review.getScore());
                appointment.setReview(review);
                appointment.setExtra("review", review);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirmAppointment(Long id, Long staffId) {
        // 检查预约是否存在且属于当前医护人员
        Appointment appointment = getOne(new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getId, id)
                .eq(Appointment::getStaffId, staffId));
        
        if (appointment == null) {
            throw new BusinessException("预约不存在或不属于当前医护人员");
        }
        
        // 验证状态
        if (appointment.getStatus() != 0) {
            throw new BusinessException("当前状态不可确认");
        }
        
        // 更新状态为已确认
        appointment.setStatus(1); // 1-已确认
        appointment.setUpdateTime(LocalDateTime.now());
        
        updateById(appointment);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rejectAppointment(Long id, Long staffId) {
        // 检查预约是否存在且属于当前医护人员
        Appointment appointment = getOne(new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getId, id)
                .eq(Appointment::getStaffId, staffId));
        
        if (appointment == null) {
            throw new BusinessException("预约不存在或不属于当前医护人员");
        }
        
        // 验证状态
        if (appointment.getStatus() != 0) {
            throw new BusinessException("当前状态不可拒绝");
        }
        
        // 更新状态为已取消
        appointment.setStatus(3); // 3-已取消
        appointment.setUpdateTime(LocalDateTime.now());
        
        updateById(appointment);
    }
    
    @Override
    public List<Appointment> getStaffTodayAppointments(Long staffId) {
        // 获取今天的开始和结束时间
        LocalDateTime todayStart = LocalDateTime.now().toLocalDate().atStartOfDay();
        LocalDateTime todayEnd = LocalDateTime.now().toLocalDate().atTime(23, 59, 59);
        
        // 查询今日预约
        List<Appointment> appointments = list(new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getStaffId, staffId)
                .between(Appointment::getAppointmentTime, todayStart, todayEnd)
                .orderByAsc(Appointment::getAppointmentTime));
        
        // 填充关联数据
        fillAssociatedData(appointments);
        
        return appointments;
    }
    
    @Override
    public Map<String, Object> getStaffAppointmentStatistics(Long staffId) {
        Map<String, Object> result = new HashMap<>();
        
        // 获取今天的开始和结束时间
        LocalDateTime todayStart = LocalDateTime.now().toLocalDate().atStartOfDay();
        LocalDateTime todayEnd = LocalDateTime.now().toLocalDate().atTime(23, 59, 59);
        
        // 统计今日预约数量
        long todayCountLong = count(new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getStaffId, staffId)
                .between(Appointment::getAppointmentTime, todayStart, todayEnd));
        
        // 统计待确认预约数量
        long pendingCountLong = count(new LambdaQueryWrapper<Appointment>()
                .eq(Appointment::getStaffId, staffId)
                .eq(Appointment::getStatus, 0));
        
        // 存入结果 - 转换为Integer
        result.put("todayCount", (int)todayCountLong);
        result.put("pendingCount", (int)pendingCountLong);
        
        return result;
    }

    /**
     * 获取预约详情（包含关联信息）
     *
     * @param id 预约ID
     * @return 预约详情VO
     */
    @Override
    public AppointmentVO getAppointmentDetail(Long id) {
        if (id == null) {
            return null;
        }

        log.info("获取预约详情，ID: {}", id);

        // 获取预约信息
        Appointment appointment = getById(id);
        if (appointment == null) {
            log.warn("预约不存在，ID: {}", id);
            return null;
        }

        // 转换为VO对象
        AppointmentVO vo = new AppointmentVO();
        BeanUtils.copyProperties(appointment, vo);

        // 设置预约用户信息
        User user = userService.getById(appointment.getUserId());
        if (user != null) {
            vo.setUserName(user.getNickname());
        }

        // 设置预约宠物信息
        Pet pet = petService.getById(appointment.getPetId());
        if (pet != null) {
            vo.setPetName(pet.getName());
        }

        // 设置预约医生信息
        Staff staff = staffService.getById(appointment.getStaffId());
        if (staff != null) {
            vo.setStaffName(staff.getName());
        }

        // 设置预约科室信息
        Department department = departmentService.getById(appointment.getDepartmentId());
        if (department != null) {
            vo.setDepartmentName(department.getName());
        }
        
        // 获取并设置评价信息
        ReviewService reviewService = SpringContextUtil.getBean(ReviewService.class);
        if (reviewService != null) {
            Review review = reviewService.getReviewByAppointmentId(id);
            if (review != null) {
                vo.setReview(review);
            }
        }

        return vo;
    }
} 